import { Client } from "./Client";
import { ClientStatus } from "./ClientStatus";
import { getFrom, getBefore, getAfter } from "./MessageQuery"
import { MessageDto } from "api/structures/dto/Message";
import { Snowflake } from "api/structures/utils/Snowflake";
import { Message } from "../structures/Message"

export class MessageStore {

    constructor(private client: Client) {}
    
    getMessages(channel_id: Snowflake, size: number, callback:(response: string[]) => void) {
        this.client.messageSortedList[channel_id] = this.client.messageSortedList[channel_id] || []
        this.client.messages[channel_id] = this.client.messages[channel_id] || {}


        if (this.client.messageSortedList[channel_id].length == 0) {
            getFrom(channel_id, (err, data) => {
                if (err) {
                    console.log("BasicChannelChat " + err.message + " " + err.stack)
                    return;
                }
                
                const newList: MessageDto[] = JSON.parse(data as string)

                if (newList.length < 50) {
                    this.client.channelsEnds[channel_id] = true

                    console.log("Mark channel as ended " + channel_id + ", " + newList.length)
                }

                this.addMessage(channel_id, newList)

                const newList0 = this.client.messageSortedList[channel_id].slice(0, 0+size)

                // this.messageSortedList[channel_id].forEach((data)=>{
                //     console.log("TTT.0 " + data)
                // })
                // console.log("=====================================")
                // newList0.forEach((data)=>{
                //     console.log("TTT.1 " + data)
                // })

                callback(newList0.reverse())
            })
        } else {
            callback(this.client.messageSortedList[channel_id].slice(0, 0+size).reverse())
        }
    }

    getMessageAfter(channel_id: Snowflake, after: Snowflake, size: number, callback:(response: string[]) => void) {
        this.client.messageSortedList[channel_id] = this.client.messageSortedList[channel_id] || []
        this.client.messages[channel_id] = this.client.messages[channel_id] || {}

        const channel = this.client.getChannelById(channel_id);

        const findIndex = this.client.messageSortedList[channel_id].indexOf(after)

        console.log("findIndex.0=" + after + ", " + findIndex + ", " + this.client.messageSortedList[channel_id].length + ", is_last=" + (channel.last_message_id == after))

        if ((channel.last_message_id == after)) {
            console.log("Return empty array becase of last_msg_id")
            callback([])
            return
        }

        if (findIndex==-1) {
            getAfter(channel_id, after, (err, data) => {
                if (err) {
                    console.log("BasicChannelChat " + err.message + " " + err.stack)
                    return;
                }
                
                const newList: MessageDto[] = JSON.parse(data as string)

                // if (newList.length < 50) {
                //     this.channelsEnds[channel_id] = true

                //     console.log("Mark channel as ended " + channel_id + ", " + newList.length)
                // }

                this.addMessage(channel_id, newList)

                const findIndex0 = this.client.messageSortedList[channel_id].indexOf(after)

                if (findIndex0 < 1) {
                    return callback([])
                }

                const minVal = Math.max(findIndex0-size, 0);
                const maxVal = Math.min(findIndex0, this.client.messageSortedList[channel_id].length);

                console.log("findIndex0.1=" + after + ", " + findIndex0 + ", " + this.client.messageSortedList[channel_id].length)

                callback(this.client.messageSortedList[channel_id].slice(minVal, maxVal).reverse())
            })
        } else {

            const minVal = Math.max(findIndex-size, 0);
            const maxVal = Math.min(findIndex, this.client.messageSortedList[channel_id].length);

            const dataGetting = this.client.messageSortedList[channel_id].slice(minVal, maxVal);

            const lastAfter = dataGetting.length ? dataGetting[0] : after;

            console.log("dataGetting.0="+ findIndex, this.client.messageSortedList[channel_id].length, dataGetting.length, size)
            console.log("dataGetting.1="+ lastAfter +", is_last=" + (channel.last_message_id == after))
            console.log("dataGetting.2="+ after, JSON.stringify(dataGetting))


            if ( dataGetting.length < size && channel.last_message_id != after) {
                getAfter(channel_id, lastAfter, (err, data) => {
                    if (err) {
                        console.log("BasicChannelChat " + err.message + " " + err.stack)
                        return;
                    }
                    
                    const newList: MessageDto[] = JSON.parse(data as string)
    
                    // if (newList.length < 50) {
                    //     this.channelsEnds[channel_id] = true

                    //     console.log("Mark channel as ended " + channel_id + ", " + newList.length)
                    // }

                    this.addMessage(channel_id, newList)
    
                    const findIndex0 = this.client.messageSortedList[channel_id].indexOf(after)

                    if (findIndex0 < 1) {
                        return callback([])
                    }

                    const minVal = Math.max(findIndex0-size, 0);
                    const maxVal = Math.min(findIndex0, this.client.messageSortedList[channel_id].length);

                    console.log("findIndex0.1=" + after + ", " + findIndex0 + ", " + this.client.messageSortedList[channel_id].length)

                    callback(this.client.messageSortedList[channel_id].slice(minVal, maxVal).reverse())
                })
            } else {
                callback(dataGetting.reverse())
            }
        }
    }

    getMessageFrom(channel_id: Snowflake, from: Snowflake, size: number, callback:(response: string[]) => void) {
        this.client.messageSortedList[channel_id] = this.client.messageSortedList[channel_id] || []
        this.client.messages[channel_id] = this.client.messages[channel_id] || {}

        
        const findIndex = this.client.messageSortedList[channel_id].indexOf(from)

        console.log("findIndex.0=" + from + ", " + findIndex + ", " + this.client.messageSortedList[channel_id].length)

        if (findIndex==-1) {
            getBefore(channel_id, from, (err, data) => {
                if (err) {
                    console.log("BasicChannelChat " + err.message + " " + err.stack)
                    return;
                }
                
                const newList: MessageDto[] = JSON.parse(data as string)

                if (newList.length < 50) {
                    this.client.channelsEnds[channel_id] = true

                    console.log("Mark channel as ended " + channel_id + ", " + newList.length)
                }

                this.addMessage(channel_id, newList)

                const findIndex0 = this.client.messageSortedList[channel_id].indexOf(from)

                if (findIndex0==-1) {
                    return callback([])
                }

                const getFromNew = findIndex0+1;
                const minVal = Math.max(getFromNew, 0);
                const maxVal = Math.min(getFromNew + size, this.client.messageSortedList[channel_id].length);

                console.log("findIndex0.1=" + from + ", " + findIndex0 + ", " + this.client.messageSortedList[channel_id].length)

                callback(this.client.messageSortedList[channel_id].slice(minVal, maxVal).reverse())
            })
        } else {

            const getFromNew = findIndex+1;
            const dataGetting = this.client.messageSortedList[channel_id].slice(getFromNew, getFromNew+size);

            const lastFrom = dataGetting.length ? dataGetting[dataGetting.length-1] : from;

            console.log("dataGetting.0="+ findIndex, this.client.messageSortedList[channel_id].length, dataGetting.length, size)
            console.log("dataGetting.1="+ lastFrom)
            console.log("dataGetting.2="+ from, JSON.stringify(dataGetting))

            if ( dataGetting.length < size && this.client.channelsEnds[channel_id] != true) {
                getBefore(channel_id, lastFrom, (err, data) => {
                    if (err) {
                        console.log("BasicChannelChat " + err.message + " " + err.stack)
                        return;
                    }
                    
                    const newList: MessageDto[] = JSON.parse(data as string)
    
                    if (newList.length < 50) {
                        this.client.channelsEnds[channel_id] = true

                        console.log("Mark channel as ended " + channel_id + ", " + newList.length)
                    }

                    this.addMessage(channel_id, newList)
    
                    // const findIndex0 = this.messageSortedList[channel_id].indexOf(from)
                    // const getFromNew = findIndex0+1;

                    // callback(this.messageSortedList[channel_id].slice(getFromNew, getFromNew+size).reverse())

                    const findIndex0 = this.client.messageSortedList[channel_id].indexOf(from)

                    if (findIndex0==-1) {
                        return callback([])
                    }

                    const getFromNew = findIndex0+1;
                    const minVal = Math.max(getFromNew, 0);
                    const maxVal = Math.min(getFromNew + size, this.client.messageSortedList[channel_id].length);

                    console.log("findIndex0.1=" + from + ", " + findIndex0 + ", " + this.client.messageSortedList[channel_id].length)

                    callback(this.client.messageSortedList[channel_id].slice(minVal, maxVal).reverse())
                })
            } else {
                callback(dataGetting.reverse())
            }
        }
    }

    addMessage(channel_id: Snowflake, messages: MessageDto[]) {

        this.client.messageSortedList[channel_id] = this.client.messageSortedList[channel_id] || []

        this.client.messages[channel_id] = this.client.messages[channel_id] || {}

        let doSort = false;

        messages.forEach((data)=>{   
            if (!this.client.messages[channel_id][data.id]) {
                this.client.messages[channel_id][data.id] = new Message(this.client, data)

                // console.log("Message create " + 
                //     "id=" + data.id + ", " +
                //     "channel_id=" + data.channel_id + ", " +
                //     "guild_id=" + data.guild_id + ", " +
                //     "content=" + data.content + ", " + 
                //     "author=" + data.author.username + "(" + data.author.global_name + ")" 
                // )



                doSort = true;

                this.client.messageSortedList[channel_id].push(data.id)
            } else {

                // console.log("Message updated " + 
                //     "id=" + data.id + ", " +
                //     "channel_id=" + data.channel_id + ", " +
                //     "guild_id=" + data.guild_id + ", " +
                //     "content=" + data.content + ", " + 
                //     "author=" + data.author.username + "(" + data.author.global_name + ")" 
                // )

                this.client.messages[channel_id][data.id]._patch(data)
            }
        })

        if (doSort) {
            console.log("DO SORT")
            this.client.messageSortedList[channel_id].sort((a, b) => {
                const snA = this.client.messages[channel_id][a]
                const snB = this.client.messages[channel_id][b]
                return snB.timestamp_number - snA.timestamp_number;
            })
        }
    }
}